﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.ServiceModel.Activation;
using System.Text;
using System.Threading.Tasks;
using YasharEl.Infrastructure.Diagnostics.Logging;
using YasharEl.Infrastructure.ObjectFactory;
using YasharEl.Infrastructure.ObjectFactory.Adapters;
using YasharEl.Infrastructure.ObjectFactory.ServiceModel;
using YasharEl.Infrastructure.ProcessEngine.DomainModel;
using YasharEl.Infrastructure.ResourcesManagement;

namespace YasharEl.Infrastructure.ProcessEngine.ServiceModel.Services
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    [ModuleService(ProcessEngineConstants.BaseName)]
    public partial class ProcessRetrieverService
    {
        #region ReadOnly Fields

        private readonly IDependencyResolver resolver;
        private readonly ILogger<ProcessRetrieverService> logger;
        private readonly ITypeAdapter typeAdapter;
        private readonly IProcessQueryManager processQueryManager;

        #endregion

        #region Constructors

        public ProcessRetrieverService(
            IDependencyResolver resolver,
            ILogger<ProcessRetrieverService> logger,
            ITypeAdapter typeAdapter,
            IProcessQueryManager processQueryManager)
        {
            Contract.Requires<ArgumentNullException>(resolver != null, "resolver could not be null.");
            Contract.Requires<ArgumentNullException>(logger != null, "logger could not be null.");
            Contract.Requires<ArgumentNullException>(typeAdapter != null, "typeAdapter could not be null.");
            Contract.Requires<ArgumentNullException>(processQueryManager != null, "processQueryManager could not be null.");

            this.resolver = resolver;
            this.logger = logger;
            this.typeAdapter = typeAdapter;
            this.processQueryManager = processQueryManager;
        }

        #endregion

        #region ProcessRetrieverService Overrides

        public override RetrieveProcessResponse RetrieveProcess(RetrieveProcessRequest request)
        {
            logger.Debug("Retrieving process {0} by application {1}...", request.WorkflowInstanceId, request.ApplicationId);

            RetrieveProcessResponse response = new RetrieveProcessResponse()
            {
            };

            IProcess foundProcess = processQueryManager.GetProcessInstance(
                request.ApplicationId,
                1,
                request.WorkflowInstanceId
            );

            if (foundProcess == null)
                throw new ProcessNotFoundException(
                    resolver.Resolve<IResourceManager>(),
                    request.WorkflowInstanceId
                );

            response.FoundProcess = typeAdapter.Adapt<IProcess, ProcessDTO>(foundProcess);

            logger.Debug("Retrieving process {0} by application {1} completed ...", request.WorkflowInstanceId, request.ApplicationId);

            return response;
        }

        #endregion
    }
}
